/*
 *  Copyright 2012 Anton Van Zyl. http://code.google.com/p/java-swiss-knife/
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
package com.knife.zip;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * A Utility to compress and unZip files and folders.
 * 
 * <br/>
 * <br/>
 * Please visit <a
 * href="http://code.google.com/p/java-swiss-knife/">Java-Swiss-Knife</a> and
 * comment, rate, contribute or raise a issue/enhancement for my library. <br/>
 * 
 * @author Anton Van Zyl
 * 
 */
public class ZipUtility {

	/**
	 * This will compress the files located in a directory.
	 * 
	 * @param inputDirectory
	 *            - The directory that needs to be compress
	 * @param outputCompressedFile
	 *            - The location of the output of the newly compressed
	 *            directory.
	 * @throws IOException
	 */
	public static final void compressDirectory(File inputDirectory, File outputCompressedFile) throws IOException {
		ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outputCompressedFile));
		compress(inputDirectory, inputDirectory, zos);
		zos.close();
	}

	private static final void compress(File directory, File base, ZipOutputStream zos) throws IOException {
		File[] files = directory.listFiles();
		byte[] buffer = new byte[8192];
		int read = 0;
		for (int i = 0, n = files.length; i < n; i++) {
			if (files[i].isDirectory()) {
				compress(files[i], base, zos);
			} else {
				FileInputStream in = new FileInputStream(files[i]);
				ZipEntry entry = new ZipEntry(files[i].getPath().substring(base.getPath().length() + 1));
				zos.putNextEntry(entry);
				while (-1 != (read = in.read(buffer))) {
					zos.write(buffer, 0, read);
				}
				in.close();
			}
		}
	}

	/**
	 * This will uncompress the files located in a compressed file.
	 * 
	 * @param inputCompressFile
	 *            - The compressed file that needs to be uncompressed.
	 * @param outputDestination
	 *            - Directory the compressed file needs to be uncompressed to
	 * @throws IOException
	 */
	public static final void uncompress(File inputCompressFile, File outputDestination) throws IOException {
		ZipFile archive = new ZipFile(inputCompressFile);
		Enumeration enumeration = archive.entries();
		while (enumeration.hasMoreElements()) {
			ZipEntry entry = (ZipEntry) enumeration.nextElement();
			File file = new File(outputDestination, entry.getName());
			if (entry.isDirectory() && !file.exists()) {
				file.mkdirs();
			} else {
				if (!file.getParentFile().exists()) {
					file.getParentFile().mkdirs();
				}

				InputStream in = archive.getInputStream(entry);
				BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));

				byte[] buffer = new byte[8192];
				int read;

				while (-1 != (read = in.read(buffer))) {
					out.write(buffer, 0, read);
				}

				in.close();
				out.close();
			}
		}
	}
}